package xiaojian.toolkit.netty.handler.codec.http.response;

import com.alibaba.fastjson.JSON;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import xiaojian.toolkit.base.SendbackResponseHelper;
import xiaojian.toolkit.bean.tlv.encode.TLVEncoderOfBean;
import xiaojian.toolkit.netty.util.NettyConstants;
import xiaojian.toolkit.util.ByteUtils;
import xiaojian.toolkit.util.Propertyable;

public class MixedSendbackResponseHelper implements SendbackResponseHelper {

	private static final Logger logger = LoggerFactory
			.getLogger(MixedSendbackResponseHelper.class);

	private NettyHttpResponseBuilder httpResponseBuilder;
	private NettyHttpResponseSender httpResponseSender;
	private TLVEncoderOfBean beanEncoder;

	public void makeAndSendback(Object responseBean, Propertyable requestBean) {
		if (logger.isDebugEnabled()) {
			logger.debug("sendback bean {} ", responseBean);
		}

		DefaultNettyResponseSource source = new DefaultNettyResponseSource();
		source.setStatus(HttpResponseStatus.OK);
		byte[] bytes;

		HttpRequest httpRequest = (HttpRequest) requestBean
				.getProperty(NettyConstants.HTTP_REQUEST);
		String contentType = httpRequest.headers().get(
				HttpHeaders.Names.CONTENT_TYPE);
		if (NettyConstants.TLV_TYPE.equalsIgnoreCase(contentType)) {
			source.setContentType(NettyConstants.TLV_TYPE);
			bytes = ByteUtils.union(beanEncoder.encode(
					responseBean,
					beanEncoder.getEncodeContextFactory().createEncodeContext(
							responseBean.getClass(), null)));
		} else if (NettyConstants.JSON_TYPE.equalsIgnoreCase(contentType)) {
			source.setContentType(NettyConstants.JSON_TYPE);
			bytes = JSON.toJSONBytes(responseBean);
		} else {
			throw new RuntimeException("UnKnown Content-Type " + contentType);
		}

		if (logger.isDebugEnabled()) {
			logger.debug("sendback bean as Hex \r\n{} ",
					ByteUtils.bytesAsTLVHexString(bytes, 8096));
		}

		source.setContent(bytes);
		source.setContentLength(bytes.length);

		HttpResponse response = httpResponseBuilder.build(source);
		if (httpRequest != null) {
			String uuid = httpRequest.headers().get(NettyConstants.HEADER_UUID);
			if (uuid != null)
				response.headers().set(NettyConstants.HEADER_UUID, uuid);
			response.headers().set(HttpHeaders.Names.CONNECTION,
					httpRequest.headers().get(HttpHeaders.Names.CONNECTION));
		}
		httpResponseSender.sendResponse((Channel) requestBean
				.getProperty(NettyConstants.PROPERTY_CHANNEL), response);

	}

	public TLVEncoderOfBean getBeanEncoder() {
		return beanEncoder;
	}

	public void setBeanEncoder(TLVEncoderOfBean beanEncoder) {
		this.beanEncoder = beanEncoder;
	}

	public NettyHttpResponseBuilder getHttpResponseBuilder() {
		return httpResponseBuilder;
	}

	public void setHttpResponseBuilder(
			NettyHttpResponseBuilder httpResponseBuilder) {
		this.httpResponseBuilder = httpResponseBuilder;
	}

	public NettyHttpResponseSender getHttpResponseSender() {
		return httpResponseSender;
	}

	public void setHttpResponseSender(NettyHttpResponseSender httpResponseSender) {
		this.httpResponseSender = httpResponseSender;
	}
}
